﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Games.Common
{
    public class History<T> where T : class
    {
        private Stack<T> history;
        private Stack<T> undos;

        public History()
        {
            history = new Stack<T>();
            undos = new Stack<T>();
        }
        public History(string text)
        {
            var inner = JsonConvert.DeserializeObject<Inner>(text, settings);
            history = new Stack<T>(inner.History);
            undos = new Stack<T>(inner.Undos);
        }
        public void Push(T t)
        {
            history.Push(t);
            undos.Clear();
        }

        public bool CanUndo()
        {
            return history.Any();
        }
        public bool CanRedo()
        {
            return undos.Any();
        }

        public void Undo(Action<T> action)
        {
            if(CanUndo())
            {
                var t = history.Pop();
                undos.Push(t);
                action?.Invoke(t);
            }
        }

        public void Redo(Action<T> action)
        {
            if(CanRedo())
            {
                var t = undos.Pop();
                history.Push(t);
                action?.Invoke(t);
            }
        }

        public void Clear()
        {
            history.Clear();
            undos.Clear();
        }

        private static JsonSerializerSettings settings = new JsonSerializerSettings
        {
            DefaultValueHandling = DefaultValueHandling.Ignore,
            Formatting = Formatting.None,
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
            NullValueHandling = NullValueHandling.Ignore
        };

        public string Serialize()
        {
            var o = new Inner { History = history.ToList(), Undos = undos.ToList() };
            return JsonConvert.SerializeObject(o, settings);
        }

        class Inner
        {
            [JsonProperty("h")]
            public List<T> History { get; set; }
            [JsonProperty("u")]
            public List<T> Undos { get; set; }
        }
    }
}
